package com.ankifyh.speakbridge;

import android.app.Application;
import android.speech.tts.TextToSpeech;
import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.idst.nui.CommonUtils;
import com.alibaba.idst.nui.Constants;
import com.alibaba.idst.nui.INativeTtsCallback;
import com.alibaba.idst.nui.NativeNui;

import java.util.Random;


//写一个能够运行“发音Runnable”的Application类
public class App extends Application {

    private static TextToSpeech sTtsInstance;
    private static String speaker;

    ///new 一个 NativeNui 的实例 nui_tts_instance
    NativeNui nui_tts_instance = new NativeNui(Constants.ModeType.MODE_TTS);
    boolean initialized =  false;
    private static final String TAG = "App";
    //  AudioPlayer默认采样率是16000
    private AudioPlayer mAudioTrack =  new AudioPlayer(new AudioPlayerCallback() {
        @Override
        public void playStart() {
            Log.i(TAG, "start play");
        }
        @Override
        public void playOver() {
            Log.i(TAG, "play over");
        }
    });

    @Override
    public void onCreate() {
        super.onCreate();
    }

    ///初始化
    public void initializeNuiTts(Runnable onNuiTtsInitializedRunnable) {
        //有TextToSpeech时则直接运行“发音Runnable”，没有时则先初始化再运行“发音Runnable”
        if (!initialized) {
            Log.i(TAG, "init tts");
            //// 这里获得当前nuisdk.aar中assets路径作为参数传给Initialize
            Initialize(CommonUtils.getModelPath(this));
            onNuiTtsInitializedRunnable.run();
        }else{
            // 每个instance一个task，若想同时处理多个task，请启动多instance
            onNuiTtsInitializedRunnable.run();
        }
    }

    ///初始化
    private void Initialize(String path) {

        int ret = nui_tts_instance.tts_initialize(new INativeTtsCallback() {
            @Override
            public void onTtsEventCallback(INativeTtsCallback.TtsEvent event, String task_id, int ret_code) {
                Log.i(TAG, "tts event:" + event + " task id " + task_id + " ret " + ret_code);
                if (event == INativeTtsCallback.TtsEvent.TTS_EVENT_START) {
                    mAudioTrack.play();
                    Log.i(TAG, "start play");
                } else if (event == INativeTtsCallback.TtsEvent.TTS_EVENT_END) {
                    /*
                     * 提示: TTS_EVENT_END事件表示TTS已经合成完并通过回调传回了所有音频数据, 而不是表示播放器已经播放完了所有音频数据。
                     */
                    Log.i(TAG, "play end");

                    // 表示推送完数据, 当播放器播放结束则会有playOver回调
                    mAudioTrack.isFinishSend(true);



                } else if (event == TtsEvent.TTS_EVENT_PAUSE) {
                    mAudioTrack.pause();
                    Log.i(TAG, "play pause");
                } else if (event == TtsEvent.TTS_EVENT_RESUME) {
                    mAudioTrack.play();
                } else if (event == TtsEvent.TTS_EVENT_ERROR) {
                    // 表示推送完数据, 当播放器播放结束则会有playOver回调
                    mAudioTrack.isFinishSend(true);

                    String error_msg =  nui_tts_instance.getparamTts("error_msg");
                    Log.e(TAG, "TTS_EVENT_ERROR error_code:" + ret_code + " errmsg:" + error_msg);
                }
            }
            @Override
            public void onTtsDataCallback(String info, int info_len, byte[] data) {
                if (info.length() > 0) {
                    Log.i(TAG, "info: " + info);
                }
                if (data.length > 0) {
                    mAudioTrack.setAudioData(data);
                    Log.i(TAG, "write:" + data.length);

                }
            }
            @Override
            public void onTtsVolCallback(int vol) {
                Log.i(TAG, "tts vol " + vol);
            }
        }, genTicket(path), Constants.LogLevel.LOG_LEVEL_VERBOSE, true);

        if (Constants.NuiResultCode.SUCCESS != ret) {
            Log.i(TAG, "create failed");
        }

        // 在线语音合成发音人可以参考阿里云官网

        // https://help.aliyun.com/document_detail/84435.html
        //这里改成不设置，发音人
        //nui_tts_instance.setparamTts("font_name", speaker);

        // 详细参数可见: https://help.aliyun.com/document_detail/173642.html
        nui_tts_instance.setparamTts("sample_rate", "24000");
        // 模型采样率设置16K，则播放器也得设置成相同采样率16K.
        mAudioTrack.setSampleRate(24000);

        nui_tts_instance.setparamTts("enable_subtitle", "1");
        // 调整语速
        nui_tts_instance.setparamTts("speed_level", "1");
        // 调整音调
//        nui_tts_instance.setparamTts("pitch_level", "0");
        // 调整音量
//        nui_tts_instance.setparamTts("volume", "1.0");


    }


    // 提供 getter 方法，供其他组件获取 TextToSpeech 对象，这里主要是为“发音Runnable”准备
    public NativeNui getNuiTts() {
        return nui_tts_instance;
    }



    @Override
    public void onTerminate() {
        if (sTtsInstance != null) {
            // 停止 TextToSpeech 并释放资源
            sTtsInstance.stop();
            sTtsInstance.shutdown();
            sTtsInstance = null;

            //
        }
        super.onTerminate();
    }


    //获取门票
    private String genTicket(String workpath) {
        String str = "";
        //获取token方式：

        // JSONObject object = new JSONObject();

        //账号和项目创建
        //  ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html
        //  object.put("app_key", "<您申请创建的app_key>"); // 必填

        //方法1：
        //  首先ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html
        //  然后请看   使用其中方案一获取临时凭证
        //  此方案简介: 远端服务器生成具有有效时限的临时凭证, 下发给移动端进行使用, 保证账号信息ak_id和ak_secret不被泄露
        //  获得Token方法(运行在APP服务端): https://help.aliyun.com/document_detail/450255.html?spm=a2c4g.72153.0.0.79176297EyBj4k
        // object.put("token", "<服务器生成的具有时效性的临时凭证>"); // 必填

        //方法2：
        //  STS获取临时凭证方法暂不支持

        //方法3：（强烈不推荐，存在阿里云账号泄露风险）
        //  参考Auth类的实现在端上访问阿里云Token服务获取SDK进行获取。请勿将ak/sk存在本地或端侧环境。
        //  此方法优点: 端侧获得Token, 无需搭建APP服务器。
        //  此方法缺点: 端侧获得ak/sk账号信息, 极易泄露。
        JSONObject object = Auth.getAliYunTicket();

        object.put("device_id", "empty_device_id"); // 必填, 推荐填入具有唯一性的id, 方便定位问题

        object.put("url", "wss://nls-gateway.cn-shanghai.aliyuncs.com:443/ws/v1"); // 默认
        //工作目录路径，SDK从该路径读取配置文件
        object.put("workspace", workpath); // 必填, 且需要有读写权限

        // 设置为在线合成
        //  Local = 0,
        //  Mix = 1,  // init local and cloud
        //  Cloud = 2,
        object.put("mode_type", "2");
        str = object.toString();
        Log.i(TAG, "UserContext:" + str);
        return str;
    }

    public String getSpeaker() {
        return speaker;
    }
}